import { BaseInputTemplateProps } from '@rjsf/utils';
import { useContext } from 'react';
import {
  BasePickInputProps,
  PickInputValueType,
  getMultiPickResultUUID,
} from '../pick-input/3d';
import {
  NumberInputFormat,
  PickInputRJSFFormat,
  selectionIDPrefix,
} from './constants';
import { PickableFormContext } from './pickable-provider';
import { PickInputForFocus } from './auto-focus/pick-input';
import {
  AmcaxBaseInputTemplate,
  FeatureManager,
  ParameterObjectType,
} from '@amcax/base';
import { decodeComposedFormat } from './utils';
import { InputWithFormatForForm } from './InputWithFormat';

const PickInputForForm = ({
  props,
  extraProps,
}: {
  props: BaseInputTemplateProps;
  extraProps: Partial<BasePickInputProps>;
}) => {
  const selectionMap = useContext(PickableFormContext);

  const uiOptions = props.uiSchema?.['ui:options'];

  const showArrow = uiOptions?.showArrow as boolean;
  const curveReversable = uiOptions?.curveReversable as boolean;
  const nameRenderer =
    uiOptions?.nameRenderer as BasePickInputProps['nameRenderer'];
  const disallowedPickType =
    uiOptions?.disallowedPickType as BasePickInputProps['disallowedPickType'];
  const pickFilter =
    uiOptions?.pickFilter as any as BasePickInputProps['pickFilter'];
  const highlightSelection =
    uiOptions?.highlightSelection as any as BasePickInputProps['highlightSelection'];
  const allowPickInvisibleAssembleFromLeftPanel =
    uiOptions?.allowPickInvisibleAssembleFromLeftPanel as boolean;

  const focusID = uiOptions?.focusID as number;
  const canBeAutoFocused = uiOptions?.canBeAutoFocused as boolean;
  const autoFocus = props.uiSchema?.['ui:autofocus'];

  const allowInfiniteLine = uiOptions?.allowInfiniteLine as boolean;
  const allowInfinitePlane = uiOptions?.allowInfinitePlane as boolean;

  const arrayIndexInfo = new RegExp(`_(\\d+)_${props.name}$`).exec(props.id);

  const arrayIndex = Number(arrayIndexInfo?.[1] ?? -1);

  return (
    <PickInputForFocus
      focusID={focusID}
      // 只有非数组的，或数组中第一个才自动focus
      autoFocus={arrayIndex <= 0 && autoFocus}
      canBeAutoFocused={canBeAutoFocused ?? true}
      allowInfiniteLine={allowInfiniteLine}
      allowInfinitePlane={allowInfinitePlane}
      showArrow={showArrow}
      curveReversable={curveReversable}
      highlightSelection={highlightSelection}
      value={[selectionMap.get(props.value)].filter((i) => i != null)}
      disabled={props.disabled}
      onPick={([pickResult]) => {
        if (pickResult == null) {
          props.onChange(null);
          return;
        }
        const uuid = getMultiPickResultUUID(pickResult);
        // rjsf会将一个选取实例递归后再生成，其中的getter等函数都会丢失
        const key = `${selectionIDPrefix}${uuid}`;

        selectionMap.set(key, pickResult);

        props.onChange(key);
      }}
      nameRenderer={nameRenderer}
      disallowedPickType={disallowedPickType}
      pickFilter={pickFilter}
      allowPickInvisibleAssembleFromLeftPanel={
        allowPickInvisibleAssembleFromLeftPanel
      }
      controlled
      placeholder={props.placeholder}
      {...extraProps}
    />
  );
};

export const CustomBaseInputTemplate = function (
  props: BaseInputTemplateProps,
) {
  const format = props.schema.format;
  const disableParameter = props.uiSchema?.['ui:options']
    ?.disableParameter as boolean;

  const allowTypeMap = {
    [PickInputRJSFFormat.PickALL]: PickInputValueType.ALL,
    [PickInputRJSFFormat.PickCurve]: PickInputValueType.Curve,
    [PickInputRJSFFormat.PickFrame]: PickInputValueType.Frame,
    [PickInputRJSFFormat.PickLine]: PickInputValueType.Line,
    [PickInputRJSFFormat.PickModel]: PickInputValueType.Model,
    [PickInputRJSFFormat.PickPlane]: PickInputValueType.Plane,
    [PickInputRJSFFormat.PickSurface]: PickInputValueType.Surface,
    [PickInputRJSFFormat.PickVertex]: PickInputValueType.Vertex,
    [PickInputRJSFFormat.PickSketch]: PickInputValueType.Sketch,
    [PickInputRJSFFormat.PickLawCurve]: PickInputValueType.LawCurve,
    [PickInputRJSFFormat.PickProduct]: PickInputValueType.Product,
    [PickInputRJSFFormat.PickPartArray]: PickInputValueType.PartArray,
  };

  const validFormats: string[] = Object.keys(allowTypeMap);

  const formats = decodeComposedFormat(props.schema.format).filter((v) =>
    validFormats.includes(v),
  );

  if (formats.length > 0) {
    const allowType = Array.from(
      new Set<PickInputValueType>(formats.map((v) => allowTypeMap[v])),
    );

    return (
      <PickInputForForm
        props={props}
        extraProps={{
          allowPickType: allowType,
        }}
      />
    );
  }

  if (
    [
      NumberInputFormat.Angle,
      NumberInputFormat.Length,
      NumberInputFormat.Real,
      NumberInputFormat.Integer,
    ].includes(format as NumberInputFormat) &&
    FeatureManager.isFeatureEnabled('unit')
  ) {
    return (
      <InputWithFormatForForm
        {...props}
        unitType={format as ParameterObjectType}
        disableParameter={disableParameter}
      />
    );
  }

  return <AmcaxBaseInputTemplate {...props} />;
};
